package com.foogui.bootrabbitmq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * rabbitmq生产者应答机制：消息发送到broker后执行的回调
 * 与配置文件中publisher-confirm-type: correlated和publisher-returns: true对应
 *
 * @author Foogui
 * @date 2023/07/07
 */
@Configuration
@Slf4j
public class RabbitmqConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
        rabbitTemplate.setMessageConverter(this.jackson2JsonMessageConverter());
        // 当 mandatory 属性被设置为 true 时：
        // 表示如果消息无法被路由到任何Exchange，RabbitMQ 不会将消息默默地丢弃，而是会触发一个 ConfirmCallback
        // 表示如果消息无法被路由到任何Queue，RabbitMQ 不会将消息默默地丢弃，而是会触发一个 ReturnCallback
        rabbitTemplate.setMandatory(true);


        // /**
        //  * 生产者只要发送消息到Exchange，ConfirmCallback回调就会触发，只不过成功时ack为true，失败为false
        //  */
        // rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
        //     String id=null;
        //     String jsonMsg=null;
        //     // correlationData如果在发送消息不传，这里就为null
        //     if (correlationData != null) {
        //         id = correlationData.getId();
        //         if (correlationData.getReturned() !=null){
        //             jsonMsg=new String(correlationData.getReturned().getMessage().getBody(),StandardCharsets.UTF_8);
        //         }
        //     }
        //     System.out.println("ConfirmCallback:     " + "相关消息元数据：" + correlationData);
        //     System.out.println("ConfirmCallback:     " + "消息id：" + id);
        //     System.out.println("ConfirmCallback:     " + "确认情况false or true：" + ack);
        //     System.out.println("ConfirmCallback:     " + "异常原因：" + cause);
        //     // 如果消息没有正常发送到交换机中
        //     if (ack) {
        //         log.info("RabbitMq.message.send.success.id: {}", id);
        //     } else {
        //         // TODO:直接补发，或者保存到数据库开始定时任务补发（表中应有是否补发的字段状态标识）
        //         log.error("RabbitMq.message.send.failed.id: {}", id);
        //         // 获取消息体，但必须在传递消息的时候，将消息放在CorrelationData.returnedMessage中
        //         log.info("sent message is {}",jsonMsg);
        //         log.error("RabbitMq.message.send.failed.cause: {}", cause);
        //     }
        // });
        //
        //
        // /**
        //  * ReturnsCallback触发条件
        //  * 1.消息没路由到队列，路由到了不触发
        //  **/
        // rabbitTemplate.setReturnsCallback(returned -> {
        //
        //     try {
        //         // 获取到发送失败的消息的消息体
        //         String messageJsonBody = new String(returned.getMessage().getBody(), StandardCharsets.UTF_8);
        //         System.out.println("ReturnCallback:     " + "消息json格式为：" + messageJsonBody);
        //         // TODO:直接补发，或者保存到数据库开始定时任务补发（表中应有是否补发的字段状态标识）
        //     } catch (Exception e) {
        //         throw new RuntimeException(e);
        //     }
        //     System.out.println("ReturnCallback:     " + "回应码：" + returned.getReplyCode());
        //     System.out.println("ReturnCallback:     " + "回应信息：" + returned.getReplyText());
        //     System.out.println("ReturnCallback:     " + "交换机：" + returned.getExchange());
        //     System.out.println("ReturnCallback:     " + "路由键：" + returned.getRoutingKey());
        //
        // });


        return rabbitTemplate;
    }

    /**
     * jackson2json消息转换器——用于转换复杂的对象为json（eg.嵌套对象，集合等）
     *
     * @return {@link Jackson2JsonMessageConverter}
     */
    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

}